package com.ming.liteflow.controller;

import cn.hutool.core.util.StrUtil;
import com.ming.common.Options;
import com.ming.common.SortBy;
import com.ming.common.beetl.util.Result;
import com.ming.common.liteflow.core.el.IvyEl;
import com.ming.common.liteflow.core.execption.LiteFlowELException;
import com.ming.common.liteflow.core.flow.LogicFlowExec;
import com.ming.common.liteflow.core.flow.logicflow.LogicFlow;
import com.ming.common.liteflow.core.node.IvyCmp;
import com.ming.common.liteflow.vo.IvyElVo;
import com.ming.common.xxljob.annotation.PermissionLimit;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.core.FlowExecutor;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.page.PageResult;
import org.beetl.sql.core.query.LambdaQuery;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/liteflow/el")
public class LiteFlowELController {

    @Resource
    private SQLManager sqlManager;

    @Resource
    private FlowExecutor flowExecutor;

//    @PostMapping("/build")
//    @PermissionLimit(limit = false)
//    public String build(@RequestBody Map<String,Object> map) throws LiteFlowELException {
//        LambdaQuery<IvyCmp> query = sqlManager.lambdaQuery(IvyCmp.class);
//        List<IvyCmp> list = query.select();
//        return Flow.NEW().nodeInfoList(list).logicFlow((String) map.get("json")).buildEL((Boolean) map.get("formatEL"));
//    }

    @PostMapping("/build/new")
    @PermissionLimit(limit = false)
    public Result<?> buildNew(@RequestBody Map<String,Object> map) throws Exception {
//        return Result.OK(LogicFlow.NEW().json((String) map.get("json")).transform().buildEL((Boolean) map.get("formatEL")));
        String el = com.ivy.parser.logicflow.LogicFlow.NEW().json((String) map.get("json")).transform().buildEL((Boolean) map.get("formatEL"));
        return Result.OK(el);
    }

//    @PostMapping("/exec")
//    @PermissionLimit(limit = false)
//    public String exec(@RequestBody Map<String,Object> map) throws LiteFlowELException {
//        LambdaQuery<IvyCmp> query = sqlManager.lambdaQuery(IvyCmp.class);
//        List<IvyCmp> list = query.select();
//        LambdaQuery<IvyDynamicClass> lambdaQuery = sqlManager.lambdaQuery(IvyDynamicClass.class);
//        List<IvyDynamicClass> dynamicClassList = lambdaQuery.select();
//        return Flow.NEW().nodeInfoList(list).dynamicClassList(dynamicClassList).logicFlow((String) map.get("json")).flowExecutor(flowExecutor).exec();
//    }

    @PostMapping("/exec/new")
    @PermissionLimit(limit = false)
    public Result<?> execNew(@RequestBody Map<String,Object> map) throws Exception {
        LambdaQuery<IvyCmp> query = sqlManager.lambdaQuery(IvyCmp.class);
        List<IvyCmp> list = query.select();
        LambdaQuery<com.ivy.builder.graph.IvyDynamicClass> lambdaQuery = sqlManager.lambdaQuery(com.ivy.builder.graph.IvyDynamicClass.class);
        List<com.ivy.builder.graph.IvyDynamicClass> dynamicClassList = lambdaQuery.select();
//        return Result.OK(LogicFlow.NEW().json((String) map.get("json")).transform().dynamicClassList(dynamicClassList).flowExecutor(flowExecutor).exec());

        String json = LogicFlowExec.NEW().json((String) map.get("json")).transform().dynamicClassList(dynamicClassList).flowExecutor(flowExecutor).exec();
        return Result.OK(json);
    }

    @PostMapping("/validate")
    @PermissionLimit(limit = false)
    public Result<?> validate(@RequestBody Map<String,Object> map) throws Exception {
        String json = (String) map.get("json");
        LambdaQuery<IvyCmp> query = sqlManager.lambdaQuery(IvyCmp.class);
        List<IvyCmp> list = query.select();

        String el = com.ivy.parser.logicflow.LogicFlow.NEW().json(json).transform().buildEL((Boolean) map.get("formatEL"));
        //String el = Flow.NEW().nodeInfoList(list).logicFlow(json).buildEL((Boolean) map.get("formatEL"));
        if(StrUtil.isBlank(el)){
            return Result.error(-1,"");
        }
        boolean validate = LiteFlowChainELBuilder.validate(el);
        if(validate){
            return Result.OK(el);
        }
        return Result.error(el);
    }

    @PostMapping("/optionEl")
    @PermissionLimit(limit = false)
    public Result<?> optionEl(@RequestBody(required = false) Map<String,Object> map) throws LiteFlowELException {
        LambdaQuery<IvyEl> query = sqlManager.lambdaQuery(IvyEl.class);
        List<IvyEl> list = query.select(IvyEl::getId,IvyEl::getElId,IvyEl::getElName);
        list = list.stream().peek(m->m.setElName(m.getElName()+"【"+m.getElId()+"】")).collect(Collectors.toList());
        return Result.OK(list);
    }

    @PostMapping("/option")
    @PermissionLimit(limit = false)
    public Result<?> elOption(@RequestBody(required = false) Map<String,Object> map) throws LiteFlowELException {
        LambdaQuery<IvyEl> query = sqlManager.lambdaQuery(IvyEl.class);
        List<IvyEl> list = query.select(IvyEl::getId,IvyEl::getElId,IvyEl::getElName);
        return Result.OK(list);
    }

    @PostMapping("/options")
    @PermissionLimit(limit = false)
    public Result<?> elOptions(@RequestBody(required = false) Map<String,Object> map) throws LiteFlowELException {
        LambdaQuery<IvyEl> query = sqlManager.lambdaQuery(IvyEl.class);
        List<IvyEl> list = query.select(IvyEl::getId,IvyEl::getElId,IvyEl::getElName,IvyEl::getSourceJson);
        return Result.OK(list);
    }

    @PostMapping("/page")
    @PermissionLimit(limit = false)
    public Result<PageResult<IvyEl>> page(@RequestBody IvyElVo vo){
        LambdaQuery<IvyEl> lambdaQuery = sqlManager.lambdaQuery(IvyEl.class);
        lambdaQuery.andEq(IvyEl::getExecutorId, LambdaQuery.filterEmpty(vo.getExecutorId()));
        lambdaQuery.andLike(IvyEl::getElId, LambdaQuery.filterLikeEmpty(vo.getElId()));
        lambdaQuery.andLike(IvyEl::getElName, LambdaQuery.filterLikeEmpty(vo.getElName()));
        Options options = vo.getOptions();
        List<SortBy> sortBy = options.getSortBy();
        for (SortBy sort : sortBy) {
            if ("desc".equalsIgnoreCase(sort.getOrder())) {
                lambdaQuery.desc(com.ming.common.beetl.util.StrUtil.camelToSnake(sort.getKey()));
            } else {
                lambdaQuery.asc(com.ming.common.beetl.util.StrUtil.camelToSnake(sort.getKey()));
            }
        }
        PageResult<IvyEl> page = lambdaQuery.page(options.getPage(), options.getItemsPerPage());
        return Result.OK(page);
    }

    @PostMapping("/add")
    @PermissionLimit(limit = false)
    public Result<?> add(@RequestBody IvyEl item) throws Exception {
        handlerEL(item);
        LambdaQuery<IvyEl> query = sqlManager.lambdaQuery(IvyEl.class);
        int i = query.insert(item);
        return Result.OK(i);
    }

    @PostMapping("/update")
    @PermissionLimit(limit = false)
    public Result<Object> update(@RequestBody IvyEl item) throws Exception {
        handlerEL(item);
        int i = sqlManager.updateTemplateById(item);
        return Result.OK("更新成功", i);
    }

    private void handlerEL(IvyEl item) throws Exception {
        item.setEl(com.ivy.parser.logicflow.LogicFlow.NEW().json(item.getFlowJson()).transform().buildEL());
    }

    @PostMapping("/delete")
    @PermissionLimit(limit = false)
    public Result<Integer> delete(@RequestBody IvyEl item){
        LambdaQuery<IvyEl> lambdaQuery = sqlManager.lambdaQuery(IvyEl.class);
        lambdaQuery.andEq(IvyEl::getId, item.getId());
        int i = lambdaQuery.delete();
        return Result.OK("删除成功",i);
    }
}
